﻿#include "DiskCoverTool.h"

DiskCoverTool::DiskCoverTool(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
	m_bReqStop = false;
	ui.pushButton_Start->setEnabled(false);
}

DiskCoverTool::~DiskCoverTool()
{
	m_bReqStop = true;
	if (m_Future.isRunning())
		m_Future.waitForFinished();
}

void DiskCoverTool::on_pushButton_ChooseDir_clicked()
{
	//Open a directory selection dialog
	QString dir = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
	if (!dir.isEmpty()) 
	{
		ui.lineEdit_Path->setText(dir);
		QString strTempFileName = dir.right(dir.size() - 1 - dir.lastIndexOf("/"));
		strTempFileName += "_DiskCover.txt";
		ui.lineEdit_TempFileName->setText(strTempFileName);
		ui.pushButton_Start->setEnabled(true);
	}
	else 
	{
		ui.lineEdit_Path->setText(tr("No directory selected"));
		ui.pushButton_Start->setEnabled(false);
	}
}

void DiskCoverTool::on_pushButton_Start_clicked()
{
	if (ui.pushButton_Start->text().contains(u8"停止"))
	{
		m_bReqStop = true;
		if (m_Future.isRunning())
			m_Future.waitForFinished();
		ui.pushButton_Start->setText(u8"开始");
		return;
	}
	if (m_Future.isRunning())
		m_Future.waitForFinished();
	// Start the disk cover process
	QString path = ui.lineEdit_Path->text();
	if (path.isEmpty() || !QDir(path).exists()) 
	{
		QMessageBox::warning(this, tr("Warning"), tr("Please select a valid directory."));
		return;
	}
	path += "/" + ui.lineEdit_TempFileName->text();
	unsigned int uiOneWriteCount = ui.spinBox_OneWriteCount->value();
	QString strErrorMessage;
	//线程池循环向文件中写入数据"This is a test data!"
	m_Future = QtConcurrent::run([&, path]() 
	{
		std::string strMess;
		for (unsigned int uiWriteCount = 0; uiWriteCount < uiOneWriteCount; uiWriteCount++)
		{
			strMess.append("This is a test data!\n");
		}
		// Simulate some processing
		FILE* fp = nullptr;
#ifdef _WIN32
		errno_t err = fopen_s(&fp, path.toStdString().c_str(), "a");
#else
		fp = fopen(path.toStdString().c_str(), "a");
#endif // _WIN32
		if (fp == nullptr) 
		{
			strErrorMessage = tr("Failed to open file for writing: %1").arg(path);
		}
		bool bOccuredError = false;
		unsigned long long ullWriteCount = 0;
		while (false == bOccuredError && false == m_bReqStop)
		{
			//向文件中写入数据"This is a test data!"
			if (fwrite(strMess.c_str(), strMess.size(), 1, fp) <= 0)
			{
				strErrorMessage = tr("Failed to write to file: %1").arg(path);
				bOccuredError = true;
			}
			ullWriteCount++;
			if (ullWriteCount % 10 == 0)
			{
				if (fp != nullptr)
				{
					//刷新文件缓存
					fflush(fp);
					portable_fflush(fp);
				}
				else
				{
					strErrorMessage = tr("Occure error while write to file: %1").arg(path);
					bOccuredError = true;
				}
			}
			//QThread::sleep(2); // Simulate a delay for the disk cover process
		}
		if (fp != nullptr)
		{
			fclose(fp);
		}		
	});
	ui.pushButton_Start->setText(u8"停止");
}

inline int DiskCoverTool::portable_fflush(FILE* file)
{
	if (fflush(file) != 0) {
		return errno;
	}

#ifdef _WIN32
	// Windows特定：获取文件描述符并强制刷新
	int fd = _fileno(file);
	if (fd == -1) {
		return errno;
	}

	// 使用Windows API将缓冲区刷新到磁盘
	HANDLE hFile = (HANDLE)_get_osfhandle(fd);
	if (hFile == INVALID_HANDLE_VALUE) {
		return EINVAL;
	}

	if (!FlushFileBuffers(hFile)) {
		return GetLastError();
	}

	return 0;
#else
	// Unix/Linux/Mac使用fsync
	int fd = fileno(file);
	if (fd == -1) {
		return errno;
	}
	return fsync(fd);
#endif
}
